// StrokeData.h: interface for the CStrokeData class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_STROKEDATA_H__5F391446_C4EC_4958_86CD_94AA7BC45660__INCLUDED_)
#define AFX_STROKEDATA_H__5F391446_C4EC_4958_86CD_94AA7BC45660__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Point.h"
#include "StrokeIndex.h"

/// a subset of binary image
struct SCoverFlag
{
public:
	SCoverFlag();
	~SCoverFlag();

public:
	int destruct(void);
	int getLargeCoverCount(int xCheck, int yCheck) const;
	BOOL initFromRect(const RECT *lpRect);
	BOOL setFlagFromPoint(const SPoint *lpPoint, int nPoint);

protected:
	/** BYTE array of the given rectangle:
	 * with 0x0f, means with x-flag;
	 * with 0xf0, means with y-flag.
	 */
	BYTE	*m_pbFlag;
	/// minimum 0-based x index, included in the rectangle
	int		m_nMinX;
	/// minimum 0-based y index, included in the rectangle
	int		m_nMinY;
	/// maximum width of the rectangle
	int		m_nMaxW;
	/// maximum height of the rectangle
	int		m_nMaxH;

protected:
	BOOL addXFlag(int x);
	BOOL addYFlag(int y);

protected:
	SCoverFlag(const SCoverFlag&);
	SCoverFlag& operator=(const SCoverFlag&);
};

/// maximum 10 key-points
const int MAX_KEYPOINT = 10;

/// data for one stroke
class CStrokeData
{
public:
	CStrokeData();
	~CStrokeData();

public:
	/// raw point
	SPoint	*m_lpSrcPoint;
	/// count of m_lpSrcPoint
	int		m_nSrcPoint;

public:
	/// simplified point
	SPoint	m_ptBuf[MAX_KEYPOINT];
	/// count of m_lpPoint
	int		m_nPoint;
	/// recognized stroke name
	STROKE_INDEX	m_eIndex;
	/// length of stroke
	float	m_fLength;
	/// only one point
	BOOL	m_fSingleDian;
	/// curve point be important or not
	int		m_nCurveType;

public:
	/// to form one-direction list
	CStrokeData	*m_pNext;

public:
	/** to create key-points
	 * @param cx maximum width of points
	 * @param cy maximum height of points
	 * @param pfStop [in] for real-time processing, to stop running fastly
	 * @param fSkipCircle to skip circle shape or not
	 * @return BOOL 1, if succeed; 0, if fail.
	 */
	BOOL createReducePoint(int cx, int cy, BOOL *pfStop, BOOL fSkipCircle, void *lpContext);
	/// to query total length of this stroke
	float getSrcPointLength(void) const;
	/// to check this is Gou(1) or Ti(2); 0 for unknown.
	int checkGouTiType(void) const;
	/// to free memory
	void destruct(void);

protected:
	BOOL locateCirclePoint(SPoint *lpCenter, RECT *lpMaxRect);
	/** to create an initial candidate indexes of key points, by checking f(x, y) = x - y
	 * \param dwCandIndex [out] output all possible indexes in LOWORD
	 * \param nMax count of dwCandIndex
	 * \param lpPoint [in] the given point array
	 * \param nPoint count of lpPoint
	 * \retval int count of outputed DWORD
	 */
	int createInitialCandIndex(DWORD *dwCandIndex, int nMax, const SPoint *lpPoint, int nPoint) const;
	/** to add more candidate indexes of key points, by checking angles
	 * \param dwCandIndex [in, out] candidate indexes to be updated
	 * \param nCandCount [in] input candidate count
	 * \param nMaxSize count of dwCandIndex
	 * \param lpPoint [in] the given point array
	 * \retval int updated count
	 */
	int updateCandIndexFromLargeAnglePoint(DWORD *dwCandIndex, int nCandCount, int nMaxSize, const SPoint *lpPoint) const;
	/** to get the rectangle of all points
	 * \param lpRect [out] output the minimum rectangle
	 * \param lpPoint [in] the given point array
	 * \param nPoint count of lpPoint
	 * \retval BOOL 1, if succeed; 0, if fail.
	 */
	static BOOL getMinMaxRect(RECT *lpRect, const SPoint *lpPoint, int nPoint);
	/** try to locate the middle point for INDEX_H_ZZP
	 * \param lpPoint [in] the given point array
	 * \param nPoint count of lpPoint
	 * \retval int 0-based index; -1, if fail.
	 */
	static int locateIndexOfHZZP(const SPoint *lpPoint, int nPoint);
	int createCandPoints(SPoint *ptOut, int nOut, const SPoint *lpPoint, int nPoint) const;
	int createSimplePoints(SPoint *ptOut, int nOut, const RECT *lpRect) const;

protected:
	CStrokeData(const CStrokeData&);
	CStrokeData& operator=(const CStrokeData&);
};

#endif // !defined(AFX_STROKEDATA_H__5F391446_C4EC_4958_86CD_94AA7BC45660__INCLUDED_)
